﻿#include "Dg5emulator.h"
#include "MiniComClient.h"

#include <QTimer>
#include <QMessageBox>

#include "QtAsioThread.h"
#include "../gloveCommands.h"


namespace vkbrd
{
	Dg5Emulator::Dg5Emulator(QWidget *parent, Qt::WFlags flags)
		: QMainWindow(parent, flags)
	{
		ui.setupUi(this);
		sendingData = false;
		closing = false;
		sendFromFile = false;
		ioThread = NULL;
		inputFile = NULL;

		sliders << ui.verticalSlider_0 << ui.verticalSlider_1 << ui.verticalSlider_2 << ui.verticalSlider_3 <<
			ui.verticalSlider_4;

		for (int i = 0; i < 100; ++i)
			ui.portNameComboBox->insertItem(i,  QString("COM") + QString::number(i));
		ui.portNameComboBox->setCurrentIndex(9); 
	}

	void Dg5Emulator::toggleSend(bool _value)
	{
		sendingData = _value;

		if (sendingData)
			sendTestMessage();

		if (_value)
		{
			try 
			{ 
				bool success  = true;
				assert(ioThread.isNull());
				ioThread = new QtAsioThread(38400, ui.portNameComboBox->currentText().toStdString());

				success &= connect(ioThread, SIGNAL(receivedData(unsigned char*, int)), this, SLOT(messageRecived(unsigned char *, int )));
				success &= connect(this, SIGNAL(dispatchWriteToPort(unsigned char)), ioThread, SLOT(writeToPort(unsigned char)));
				success &= connect(this, SIGNAL(stopIOThread()), ioThread, SLOT(stop()));
				assert(success);
			
				ioThread->start();
				QTimer::singleShot(0, ioThread, SLOT(pollLoop()));

				sendingData = true;
				sendTestMessage();
			} 
			catch (std::exception& e) 
			{ 
				QMessageBox msgBox;
				msgBox.setText(QString("Error while creating port connection: ") + e.what());
				msgBox.exec();
				QTimer::singleShot(0, ui.activateSendCheckBox, SLOT(toggle())); //uncheck sending active
			} 
		}
		else
		{
			TerminateIOThread();
		}
	}

	Dg5Emulator::~Dg5Emulator()
	{

	}

	void Dg5Emulator::getSlidervalue( int _sliderNum, char* _msg,char _extraBits /*=0*/)
	{
		int sliderValue = sliders[_sliderNum]->value();

		char highValue = (sliderValue >> 5) & e5BitMask;

		_msg[2*_sliderNum] = _extraBits | highValue;
		_msg[2*_sliderNum+1] = sliderValue & e5BitMask;
	}

	void Dg5Emulator::sendTestMessage()
	{
		if (!sendingData)
			return;

		char msg[messageLenght];

		if (sendFromFile)
			constructMessageFromFile(msg);
		else
			constructMessageFromSliders(msg);
		
		QString status("Sending message: ");

		for (int i = 0 ; i < messageLenght; ++i)
		{
			QString hexNum = QString::number((unsigned char) msg[i], 16);
			if (hexNum.length() < 2)
				hexNum.prepend("0");
			status.append(hexNum);
			status.append(" ");
			emit(dispatchWriteToPort(msg[i]));
		}

		ui.statusBar->showMessage(status);

		//Loop
		QTimer::singleShot(ui.intervalSpinBox->value(), this, SLOT(sendTestMessage()));
	}

	void Dg5Emulator::messageRecived(unsigned char* readMsg, int bytesTransferred )
	{
		for (int i = 0; i < bytesTransferred; ++i)
		{
			switch (readMsg[i])
			{
			case eResetCommand:
				sendingData = false;
				ui.statusBar->showMessage("Received ResetCommand. Standby mode");
				break;
			case eStartCommand:
				if (!sendingData)
				{
					sendingData = true;
					QTimer::singleShot(ui.intervalSpinBox->value(), this, SLOT(sendTestMessage()));
				}
				break;
			case eRequestInfo:
				ui.statusBar->showMessage("Received Request info command, response not implemented yet");
				break;
			default:
				ui.statusBar->showMessage(QString("Received invalid command: ") + QString::number((unsigned char)readMsg, 16));
			}
		}
	}

	void Dg5Emulator::openDatafile()
	{
		if (inputFile == NULL)
		{
			inputFile = new QFile("./realFingerData/bend_left_OX.log");
			if (!inputFile->open (QFile::ReadOnly))
				assert(false);
			inputFileStream = new QTextStream(inputFile);
			inputFileStream->setIntegerBase(16);
			pos = 0;
		}
	}

	char Dg5Emulator::getByteFromFile()
	{
		int val = -1; 
		(*inputFileStream) >> val;
		if(inputFileStream->atEnd())
		{
			inputFileStream->seek(0);
			(*inputFileStream) >> val;
		}
		return val;
	}

	void Dg5Emulator::closeEvent( QCloseEvent* _event )
	{
		TerminateIOThread();
	}

	void Dg5Emulator::constructMessageFromFile( char * msg )
	{
		openDatafile();
		for (int i = 0; i < messageLenght; ++i)
			msg[i] = getByteFromFile();
	}

	void Dg5Emulator::constructMessageFromSliders( char * msg)
	{
		char extraBits[fingerCount] = {1 << 7, 0, 0, 0, 0};

		for (int i = 0; i < fingerCount; ++i)
			getSlidervalue(i, msg, extraBits[i]);

		for (int i = 10; i < messageLenght; ++i) //Pos //Tracker
			msg[i] = 0;
	}

	void Dg5Emulator::toggleSendSource( bool _value )
	{
		sendFromFile = _value;
	}

	void Dg5Emulator::TerminateIOThread()
	{
		if (!ioThread.isNull())
		{
			emit stopIOThread();
			ioThread->wait();
			delete ioThread;
		}
	}

} //namespace vkbrd